using System;

namespace Synergy.Extensions
{
	/// <summary>
	/// Extension methods for the <see cref="DateTime"/> class.
	/// </summary>
	/// <remarks>
	///		<list type="table">
	///			<listheader><term>Version</term><description>Description</description></listheader>
	///			<item>
	///				<term>1.0</term>
	///				<description>Initial version</description>
	///			</item>
	///		</list>
	/// </remarks>
	public static class DateTimeExtension
	{
		#region | Year |

		/// <summary>
		/// Gets the first day of the year in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <returns>The first day of the year.</returns>
		public static DateTime GetFirstDayOfYear(this DateTime date)
		{
			return new DateTime(date.Year, 1, 1);
		}


		/// <summary>
		/// Gets the last second of the last day of the year in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <returns>The last day of the year.</returns>
		public static DateTime GetLastDayOfYear(this DateTime date)
		{
			return date.GetFirstDayOfYear().AddYears(1).AddTicks(-1);
		}

		#endregion


		#region | Month |

		/// <summary>
		/// Gets the first day of the month in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <returns>The first day of the month.</returns>
		public static DateTime GetFirstDayOfMonth(this DateTime date)
		{
			return new DateTime(date.Year, date.Month, 1);
		}


		/// <summary>
		/// Gets the last second of the last day of the month in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <returns>The last day of the month.</returns>
		public static DateTime GetLastDayOfMonth(this DateTime date)
		{
			return date.GetFirstDayOfMonth().AddMonths(1).AddTicks(-1);
		}

		#endregion


		#region | Week |

		/// <summary>
		/// Gets the first day of the week in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <returns>The first day of the week.</returns>
		public static DateTime GetFirstDayOfWeek(this DateTime date)
		{
			return GetFirstDayOfWeek(date, DayOfWeek.Sunday);
		}


		/// <summary>
		/// Gets the first day of the week in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <param name="firstDayOfWeek">The first day of week.</param>
		/// <returns>The first day of the week.</returns>
		public static DateTime GetFirstDayOfWeek(this DateTime date, DayOfWeek firstDayOfWeek)
		{
			var start = date.AddDays((int)firstDayOfWeek - (int)date.DayOfWeek);
			return new DateTime(start.Year, start.Month, start.Day);
		}


		/// <summary>
		/// Gets the last second of the last day of the week in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <returns>The last day of the week.</returns>
		public static DateTime GetLastDayOfWeek(this DateTime date)
		{
			return GetLastDayOfWeek(date, DayOfWeek.Sunday);
		}


		/// <summary>
		/// Gets the last second of the last day of the week in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <param name="firstDayOfWeek">The first day of week.</param>
		/// <returns>The last day of the week.</returns>
		public static DateTime GetLastDayOfWeek(this DateTime date, DayOfWeek firstDayOfWeek)
		{
			return date.GetFirstDayOfWeek(firstDayOfWeek).AddDays(7).AddTicks(-1);
		}

		#endregion


		#region | Day |

		/// <summary>
		/// Gets the beginning of the day in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <returns>The beginning of the day.</returns>
		public static DateTime GetMidnight(this DateTime date)
		{
			return new DateTime(date.Year, date.Month, date.Day);
		}


		/// <summary>
		/// Gets the end of the day in the specified <paramref name="date"/>.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <returns>The end of the day.</returns>
		public static DateTime GetEndOfDay(this DateTime date)
		{
			return date.GetMidnight().AddDays(1).AddTicks(-1);
		}

		#endregion
	}
}